<?php

// Namespace

namespace Loop;


// Dependencies

require_once(PATH_LOOP . 'Class/CTarDriver.php');
require_once(PATH_LOOP . 'Class/CCsvFactory.php');


/**
 * @package		Loop
 * @category	Factory
 */

class CStringFactory
{

	/**
	 *
	 */

	public function __construct()
	{
		// Define unviverse

		$this->universe = pref('[Loop]/application/universe');


		// Define path to translations

		$this->pathToStrings = path
		(
			array
			(
				PATH_APPLICATION,
				'Data',
				'String'
			),
			true
		);



		// Define languages

		$this->languages  = pref('[Loop]/localization/languages');	


		$this->csvFactory = new \Loop\CCsvFactory();	
	}


	/**
	 *
	 */
	
	public function api_import()
	{
		$full = fv('full', true);

		// Call the method
		
		$result = $this->import($full);
		
		
		return $result;
	}


	/**
	 *
	 */
	
	public function api_export()
	{
		// Call the method
		
		$result = $this->export();
		
		
		return $result;
	}


	/**
	 *
	 */

	public function createPhpFile($pathToFolderString, $pathToCsv, $fileName, $full)
	{
		// Get the extension

		$extension = '.' . pathinfo($pathToCsv, PATHINFO_EXTENSION);

		
		// Calcul the length of the extension

		$length = strlen($extension);


		// Get the name of the file without extension

		$fileName = substr($fileName, 0, -$length);

	
		// Get the name of the file

		$results = $this->getDataTranslationFromCsv($pathToCsv, $full);


		// Build the file

		foreach ($results as $language => $result)
		{
			// Ensure the path tranlation extension exists

			$pathToFolderString = path
			(
				array 
				(
					$pathToFolderString
				),
				true
			);


			// Create the path to the file

			$pathToPhpFile = $pathToFolderString . '/'. $fileName .'_' . $language . '.php';


			// Is the mode full ?

			if ($full == false)
			{
				// Empty variables STRING

				app()->getVariableManager()->deleteVariableGroup('STRING');
				

				// Is the translation file existing ?

				if (file_exists($pathToPhpFile) === false)
						{
					// The file did not exist

					continue;
				}


				// Execute the file

				require($pathToPhpFile);

			
				// Get the translations

				$stringTranslations = v('STRING::'.'*');	

				
				// Is it translation?

				if (is_array($stringTranslations) === false)
				{
					continue;
				}


				// Create the array

				foreach ($stringTranslations as $translation => $stringTranslation)
				{
					if (array_key_exists($translation, $result) === false)
					{
						$result[$translation] = $stringTranslation;
					}
				}
			}
					

			// Open the php file

			$handle = fopen($pathToPhpFile, "w");


			// Set the first line

			fwrite($handle, "<?php \r\n\r\n");


			// For each translation, write it in file

			foreach ($result as $translate => $translation)
			{
				fwrite($handle, "str('$translate', ' " . addslashes($translation) . "'); \r\n");
			}


			// Set the final line
			
			fwrite($handle, "\r\n?>");
		}
	}


	/**
	 *
	 */

	public function export()
	{
		// Create new object

		$tarDriver = new \Loop\CTarDriver();


		// Get the translations to export

		$results = $this->getArrayDataTranslation();


		// Create the data for the first csv line

		array_unshift($this->languages, 'code');


		// For each entry

		foreach ($results as $extension => $directories)
		{

			// For each directories/file found

			foreach ($directories as $nameDirectory => $concept)
			{
				// Special case for common

				if($nameDirectory == 'Common')
				{
					// Ensure the path tranlation extension exists

					$pathToFile = path
					(
						array 
						(
							$this->pathToStrings,
							$extension
						),
						true
					);	


					// Construct the path to the file

					$pathToFileCsv = $pathToFile . $nameDirectory . '.csv';


					// Open the file

					$handle = $this->csvFactory->open($pathToFileCsv, 'w');


					// Set the first line

					$this->csvFactory->write($handle, $this->languages);


					// Set each line

					foreach ($concept as $data) 
					{
						$this->csvFactory->write($handle, $data);
					}


					// Close the file

					$this->csvFactory->close($handle);

					continue;
				}


				// Ensure the path tranlation extension exists

				$pathToFile = path
				(
					array 
					(
						$this->pathToStrings,
						$extension,
						$nameDirectory
					),
					true
				);		


				// For each file to create

				foreach ($concept as $conceptName => $datas)
				{
					// Construct the path to the file

					$pathToFileCsv = $pathToFile . $conceptName . '.csv';


					// Open the file

					$handle = $this->csvFactory->open($pathToFileCsv, 'w');


					// Set the first line

					$this->csvFactory->write($handle, $this->languages);


					// Set each line

					foreach ($datas as $data) 
					{
					    $this->csvFactory->write($handle, $data);
					}


					// Close the file

					$this->csvFactory->close($handle);
				}
			}
		}


		// Createarchive

		$tarDriver->save
		(
			path
			(
				array
				(
					PATH_APPLICATION,
					'Data'
				)
			) ,
			'String',
			'Strings.tar'
		);
	}



	/**
	 *
	 */

	public function getArrayDataTranslation()
	{
		// Create array language

		$languagesArrayKeys['code'] = null;

		foreach ($this->languages as $language)
		{
			$languagesArrayKeys[$language] = null;
		}


		// Get ids of extensions
		
		$extensionIds = app()->getExtensionManager()->getExtensionsIds();


		// Get the concepts to excluded 

		$excludedConcepts = pref('[Loop]/strings/excludedConcepts');


		// Get the allowed extensions

		$allowedExtensions =  pref('[Loop]/strings/allowedExtensions');


		// 

		$result = array();


		// For each path found

		foreach ($extensionIds as $extensionId)
		{
			// 

			$result[$extensionId] = array();


			// Get the id of the extension

			$pathToExtension = app()->getPathHelper()->convertExtensionIdToPath($extensionId);


			// Open the directory

			$trunkDirectory = opendir($pathToExtension);


			// Get all the directories found

			while ($directory = readdir($trunkDirectory)) 
			{ 	
				// Is it an excluded directory ?

				if (array_search($directory, $excludedConcepts) !== false)
				{
					// The directory is excluded

					continue;
				}
				

				//

				$result[$extensionId][$directory] = array();

				
				// Construct path to the string directory

				$pathToString = 'String/' . $directory;


				// Get the directory's files

				$filesInDirectory= scandir($pathToExtension . $directory);


				// Initialize the array of file to translate

				$filesToTranslate = array();

				
				// For each file found

				foreach ($filesInDirectory as $fileInDirectory)
				{
					// Is it a directory ?

					if (is_dir($fileInDirectory))
					{
						continue;
					}


					// Get the extension

					$extension = '.' . pathinfo($pathToExtension . $directory . $fileInDirectory , PATHINFO_EXTENSION);


					// Is the extention allowed ?

					if (array_search($extension, $allowedExtensions) === false)
					{
						// The extension is not allowed

						continue;
					}			


					// Calcul the length of the extension

					$length = strlen($extension);


					// Get the name of the file without extension

					$fileName = substr($fileInDirectory, 0, -$length);
	

					// Does the filename already exist in the array ?

					if (array_search($fileName, $filesToTranslate) !== false)
					{
						// The directory is excluded

						continue;
					}

					$filesToTranslate[] = $fileName;
				}


				// For each file to transles

				foreach ($filesToTranslate as $fileToTranslate)
				{
					// Initialize the resutl

					$result[$extensionId][$directory][$fileToTranslate] = array();


					// For each language authorized

					foreach ($this->languages as $language)
					{
						// Construct the name of the translation file

						$nameOfTranslateFile = $fileToTranslate . '_' . $language . '.php';						


						// Define the path to the file

						$pathToFileTranslation = $pathToExtension . $pathToString . '/' . $nameOfTranslateFile;


						// Is the translation file existing ?

						if (file_exists($pathToFileTranslation) === false)
						{
							// The file did not exist

							continue;
						}


						// Empty variables STRING

						app()->getVariableManager()->deleteVariableGroup('STRING');


						// Execute the file

						require($pathToFileTranslation);


						// Get the translations

						$stringTranslations = v('STRING::'.'*');


						// Is it empty ?

						if (is_array($stringTranslations) === false)
						{
							continue; 
						}


						// For each string found

						foreach ($stringTranslations as $stringToTranslate => $stringTranslation)
						{
							// The key does not exist, create it for all the languages

							if (array_key_exists($stringToTranslate, $result[$extensionId][$directory][$fileToTranslate]) === false)
							{
								$result[$extensionId][$directory][$fileToTranslate][$stringToTranslate] = $languagesArrayKeys;

								$result[$extensionId][$directory][$fileToTranslate][$stringToTranslate]['code'] = $stringToTranslate;
							}

						 
							// Set the value for the current language

							$result[$extensionId][$directory][$fileToTranslate][$stringToTranslate][$language] = $stringTranslation;
						}				
					}	
				}	
			}


			// Special Case for STRING/Common

			$commonName = 'Common';


			// For each language

			foreach($this->languages as $language)
			{
				// Create the name of the common file

				$nameOfCommonFile = $commonName . '_' . $language . '.php';


				// Construct the path to the file

				$pathToFile = $pathToExtension . 'String/' . $nameOfCommonFile;


				// If the file existing ?

				if (file_exists($pathToFile) === true)
				{
					// Is the entry alreay exist ?

					if (array_key_exists($commonName, $result[$extensionId]) === false)
					{
						$result[$extensionId][$commonName] = array();
					}


					// Empty variables STRING

					app()->getVariableManager()->deleteVariableGroup('STRING');


					// Execute the file

					require($pathToFile);


					// Get the translations

					$stringTranslations = v('STRING::'.'*');					

					
					// For each string found

					foreach ($stringTranslations as $stringToTranslate => $stringTranslation)
					{
						// The key does not exist, create it for all the languages

						if (array_key_exists($stringToTranslate, $result[$extensionId][$commonName]) === false)
						{
							$result[$extensionId][$commonName][$stringToTranslate] = $languagesArrayKeys;

							$result[$extensionId][$commonName][$stringToTranslate]['code'] = $stringToTranslate;
						}

						// Set the value for the current language

						$result[$extensionId][$commonName][$stringToTranslate][$language] = $stringTranslation;
					}		
				}
			}	


			//.Close the trunk directory

			closedir($trunkDirectory);
		}	


		return $result;
	}


	/**
	 *
	 */

	public function getDataTranslationFromCsv($pathToCsv)
	{
		// Open the csv

		$handle = $this->csvFactory->open($pathToCsv, 'r');


		// Get the first line 

		$firstLine = $this->csvFactory->getColumns($handle);


		// Is the first line correct ?

		if 
		(
			is_array($firstLine) === true &&
			$firstLine[0] != 'code'
		)
		{
			e(EXCEPTION_ARRAY_KEY_EXPECTED);
		}


		// Unset the column code

		array_shift($firstLine);


		// Create array for result

		$strings = array();
		$languages = array();


		// For each language found

		foreach ($firstLine as $column)
		{
			$strings[$column] = array();
			$languages[] = $column;
		}


		// Set the code

		array_unshift($firstLine, 'code');


		// For each line found, build result

		while ($records = $this->csvFactory->read($handle))
		{
			foreach ($records as $data)
			{
				$values = array_combine($firstLine, $data);

				foreach ($languages as $language)
				{
					$strings[$language][$values['code']] = $values[$language];
				}
			}
		}		


		return $strings;
	}


	/**
	 *
	 */

	public function import($full)
	{
		// Open the string directory which contains csv 

		$trunkDirectory = opendir($this->pathToStrings);


		// Get the concepts to excluded 

		$excludedConcepts = pref('[Loop]/strings/excludedConcepts');


		// Get all the directories or file found

		while ($directory = readdir($trunkDirectory)) 
		{ 	
			// Get the directory's files

			$filesInDirectory= scandir($this->pathToStrings . '/' . $directory);


			// Can you process this file/directory ?

			if (array_search($directory, $excludedConcepts) !== false)
			{
				// The directory is excluded

				continue;
			}	


			// For each file/folder found

			foreach ($filesInDirectory as $fileInDirectory)
			{
				// Is it an excluded directory ?

				if (array_search($fileInDirectory, $excludedConcepts) !== false)
				 {
					// The directory is excluded

					continue;
				}	
				

				// Create the path to the csv

				$pathToCsv = $this->pathToStrings . '/' . $directory . '/' . $fileInDirectory;


				//

				if ($directory == EXTENSION_APPLICATION)
				{
					// Path to the folder string

					$pathToFolderString = PATH_APPLICATION  . 'String';
				}
				else
				{
					$pathToFolderString = PATH_EXTENSION . $directory . '/String';
				}


				// Is it a directory ?

				if (is_dir($pathToCsv))
				{
					$extensionDirectory = opendir($pathToCsv);
					

					// Get all the sub directories found

					while ($subDirectory = readdir($extensionDirectory)) 
					{ 	

						// Is it an excluded directory ?

						if (array_search($subDirectory, $excludedConcepts) !== false)
						{
							// The directory is excluded

							continue;
						}	
						

						// Variables

						$pathFolderString = path
						(
							array 
							(
								$pathToFolderString,
								$fileInDirectory
							),
							true
						);

						//$pathFolderString =  $pathToFolderString . '/' . $fileInDirectory;
						$pathCsv = $pathToCsv .'/' . $subDirectory;


						// Create the php file

						$this->createPhpFile($pathFolderString, $pathCsv , $subDirectory, $full);

					}

					continue;
				}


				// Create the php file

				$this->createPhpFile($pathToFolderString, $pathToCsv, $fileInDirectory, $full);	
			}
		}
	}
}

?>